#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

template <class T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }

    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

    void Lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }

    void Unlock(pthread_mutex_t &mutex)
    {
        pthread_mutex_unlock(&mutex);
    }

public:
    RingQueue(int cap)
        : _cap(cap), _productor_step(0), _consumer_step(0), _ring_queue(cap)
    {
        sem_init(&_data_sem,0,0);
        sem_init(&_room_sem,0,_cap);

        pthread_mutex_init(&_productor_mutex,nullptr);
        pthread_mutex_init(&_consumer_mutex,nullptr);
    }

    void Enqueue(T &in)
    {
        P(_room_sem);
        Lock(_productor_mutex);
        _ring_queue[_productor_step] = in;
        _productor_step++;
        _productor_step %= _cap;
        V(_data_sem);
        Unlock(_productor_mutex);
    }

    void Popqueue(T *out)
    {
        P(_data_sem);
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step];
        _consumer_step++;
        _consumer_step %= _cap;
        V(_room_sem);
        Unlock(_consumer_mutex);
    }

    ~RingQueue()
    {
        sem_destroy(&_data_sem);
        sem_destroy(&_room_sem);
        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }

private:
    // 1.环形队列和最大容量
    std::vector<T> _ring_queue;
    int _cap;

    // 2.生产和消费下标
    int _productor_step;
    int _consumer_step;

    // 3.定义信号量
    sem_t _room_sem;
    sem_t _data_sem;

    // 4.定义锁
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};